// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use num_cpus;
use tokio::sync::mpsc;
use tauri::{App, AppHandle, Manager, Result as TauriResult};
use log::{info, error};
use url::Url;
use serde::{Deserialize, Serialize};

// 任务类型
enum Task {
    YoutubeUrl(String),
    YoutubePlaylist(String),
}

// 任务队列管理器
struct TaskQueue {
    sender: mpsc::Sender<Task>,
    receiver: Arc<Mutex<mpsc::Receiver<Task>>>,
}

impl TaskQueue {
    // 创建新的任务队列
    fn new() -> Self {
        let (sender, receiver) = mpsc::channel(100);
        Self {
            sender,
            receiver: Arc::new(Mutex::new(receiver)),
        }
    }

    // 添加任务到队列
    async fn add_task(&self, task: Task) -> Result<(), mpsc::error::SendError<Task>> {
        self.sender.send(task).await
    }

    // 启动线程池处理任务
    fn start_processing(&self, app_handle: AppHandle) {
        let num_workers = num_cpus::get();
        info!("启动 {} 个工作线程", num_workers);

        let receiver = self.receiver.clone();

        for id in 0..num_workers {
            let receiver = receiver.clone();
            let app_handle = app_handle.clone();

            thread::spawn(move || {
                info!("工作线程 {} 已启动", id);
                let rt = tokio::runtime::Runtime::new().unwrap();

                loop {
                    let task = {
                        let mut receiver = receiver.lock().unwrap();
                        rt.block_on(async { receiver.recv().await })
                    };

                    match task {
                        Some(task) => {
                            rt.block_on(async {
                                if let Err(e) = process_task(task, &app_handle).await {
                                    error!("处理任务失败: {}", e);
                                }
                            });
                        },
                        None => {
                            info!("工作线程 {} 没有更多任务，退出", id);
                            break;
                        }
                    }
                }
            });
        }
    }
}

// 处理单个任务
async fn process_task(task: Task, app_handle: &AppHandle) -> Result<(), String> {
    match task {
        Task::YoutubeUrl(url) => {
            info!("处理YouTube URL: {}", url);
            // 模拟处理单个视频
            simulate_processing(&url, app_handle).await;
            Ok(())
        },
        Task::YoutubePlaylist(url) => {
            info!("处理YouTube播放列表: {}", url);
            // 从播放列表中提取视频并添加到队列
            extract_videos_from_playlist(&url, app_handle).await;
            Ok(())
        },
    }
}

// 模拟处理单个视频
async fn simulate_processing(url: &str, app_handle: &AppHandle) {
    // 模拟处理进度
    for i in 0..=100 {
        thread::sleep(Duration::from_millis(50));
        let progress = i as f64 / 100.0;
        let message = format!("处理 {}: {:.1}%", url, progress * 100.0);
        info!("{}", message);

        // 发送进度更新到前端
        if let Err(e) = app_handle.emit("download_progress", &serde_json::json!({"url": url, "progress": progress, "status": "processing"})) {
            error!("发送进度更新失败: {}", e);
        }
    }

    // 模拟完成
    if let Err(e) = app_handle.emit("download_progress", &serde_json::json!({
        "url": url,
        "progress": 1.0,
        "status": "completed"
    })) {
        error!("发送完成通知失败: {}", e);
    }
}

// 从播放列表提取视频
async fn extract_videos_from_playlist(playlist_url: &str, app_handle: &AppHandle) {
    // 获取应用状态中的任务队列
    let app_state = app_handle.state::<AppState>();
    let task_queue = app_state.task_queue.lock().unwrap();

    // 实际应用中，这里应该使用 yt-dlp 或其他库来获取播放列表中的视频
    // 这里我们模拟提取5个视频
    for i in 1..=5 {
        let video_url = format!("{}/video{}?t={}", playlist_url, i, i*10);
        info!("从播放列表提取视频: {}", video_url);

        // 添加到队列
        if let Err(e) = task_queue.add_task(Task::YoutubeUrl(video_url.clone())).await {
            error!("添加视频到队列失败: {}", e);
        }

        // 发送播放列表处理进度到前端
        if let Err(e) = app_handle.emit("playlist_progress", &serde_json::json!({
            "playlist_url": playlist_url,
            "current": i,
            "total": 5,
            "status": "extracting"
        })) {
            error!("发送播放列表进度更新失败: {}", e);
        }

        thread::sleep(Duration::from_secs(1));
    }

    // 发送播放列表处理完成通知
    if let Err(e) = app_handle.emit("playlist_progress", &serde_json::json!({
        "playlist_url": playlist_url,
        "current": 5,
        "total": 5,
        "status": "completed"
    })) {
        error!("发送播放列表完成通知失败: {}", e);
    }
}

// 应用状态
struct AppState {
    task_queue: Mutex<TaskQueue>,
}

fn main() {
    // 初始化日志
    env_logger::init();

    info!("启动 Bootleg Link NG 应用程序...");

    let task_queue = TaskQueue::new();

    tauri::Builder::default()
        .setup(move |app| {
            // 设置应用状态
            let app_state = AppState {
                task_queue: Mutex::new(task_queue.clone()),
            };
            app.manage(app_state);

            // 启动任务处理
            let app_handle = app.handle();
            task_queue.start_processing(app_handle);

            Ok(())
        })
        .invoke_handler(tauri::generate_handler![add_url_task])
        .run(tauri::generate_context!())
        .expect("运行应用程序时出错");
}

// Tauri命令：添加URL任务
#[tauri::command]
async fn add_url_task(app: AppHandle, url: String) -> TauriResult<()> {
    info!("接收到URL任务: {}", url);

    // 判断是否是有效的URL
    let parsed_url = match Url::parse(&url) {
        Ok(url) => url,
        Err(e) => {
            error!("无效的URL: {}", e);
            return Err(tauri::Error::from(e.to_string()));
        }
    };

    // 获取URL主机
    let host = parsed_url.host_str().unwrap_or("");

    // 判断是否是YouTube URL
    if host.contains("youtube.com") || host.contains("youtu.be") {
        // 检查是否是播放列表
        let is_playlist = parsed_url.query_pairs()
            .any(|(key, _)| key == "list");

        let app_state = app.state::<AppState>();
        let task_queue = app_state.task_queue.lock().unwrap();

        if is_playlist {
            task_queue.add_task(Task::YoutubePlaylist(url)).await
                .map_err(|e| tauri::Error::from(e.to_string()))?;
        } else {
            task_queue.add_task(Task::YoutubeUrl(url)).await
                .map_err(|e| tauri::Error::from(e.to_string()))?;
        }
    } else {
        error!("不支持的URL主机: {}", host);
        return Err(tauri::Error::from(format!("不支持的URL主机: {}", host)));
    }

    Ok(())
}